package fr.sedoo.rbv.geonetwork.request;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.StringWriter;

import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.StringRequestEntity;
import org.apache.commons.io.IOUtils;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.input.SAXBuilder;

import fr.sedoo.rbv.geonetwork.config.GeonetworkConfig;
import fr.sedoo.rbv.geonetwork.domain.GeonetworkUser;

public class MetadataAddOrUpdateWithIdRequest extends AbstractCSWRequest 
{
	
	private static final String CHARACTER_STRING = "CharacterString";
	private static final String FILE_IDENTIFIER = "fileIdentifier";
	private static final String METADATA_UUID_KEY = "metadata_uuid_key";
	private static final String EXCEPTION_REPORT = "ExceptionReport";
	String content="";
	private boolean harvested=true;
	private String uuid;
	
	public MetadataAddOrUpdateWithIdRequest(String content, GeonetworkConfig config)
	{
		super(config);
		this.content = content;
		
	}
	
	public MetadataAddOrUpdateWithIdRequest(String content, GeonetworkUser user)
	{
		super(user);
		this.content = content;
		
	}
	
	public MetadataAddOrUpdateWithIdRequest(String content)
	{
		super();
		this.content = content;
		
	}
	
	public boolean execute() throws Exception
	{
		
			
			
			/*
			 * On parse la chaine passé afin de pouvoir ajouter le contenu à la requete
			 */
			
			SAXBuilder sxb = new SAXBuilder();
			Document document = sxb.build(new ByteArrayInputStream(content.getBytes()));
			Element rootElement = document.detachRootElement();
			
			
			// Vérification de la présence de uuid
			
			Element uuidElement = rootElement.getChild(FILE_IDENTIFIER, gmdNamespace);
			if (uuidElement == null)
			{
				throw new Exception("uuid not present");
			}
			Element child = uuidElement.getChild(CHARACTER_STRING, gcoNamespace);
			if (child == null)
			{
				throw new Exception("uuid not present");
			}
			setUuid(child.getText().trim());

			
			MetadataExistRequest existRequest = new MetadataExistRequest(getUuid(), getUser());
			boolean exists = existRequest.execute();
			Element headElement = null; 
			if (exists)
			{
				headElement = new Element("Update",cswNamespace);
			}
			else
			{
				headElement = new Element("Insert",cswNamespace);	
			}
			
			
			Element request = getCSWRootElement();
			request.addContent(headElement);
			headElement.addContent(rootElement);

			String cswURL = getConfig().getCSWPublicationURL();
			PostMethod post = new PostMethod(cswURL);

			try {
				String postData = getString(new Document(request));
				post.setRequestEntity(new StringRequestEntity(postData,"application/xml", UTF8));
					String rawXml =executePostMethod(post);
					if (rawXml.length()>0)
					{
						if (rawXml.contains(EXCEPTION_REPORT))
						{
							if (rawXml.contains(METADATA_UUID_KEY))
							{
								throw new Exception("Existing key - "+rawXml);
							}
							else
							{
								throw new Exception(rawXml);
							}
						}
						else
						{
							CSWRequestResult requestResult = CSWRequestResult.fromXML(rawXml);
							if ((requestResult.getTotalUpdated() == 1) || (requestResult.getTotalInserted()==1))
							{
								//Temporisation pour s'assurer que Géonetwork s'est mis à jour
								Thread.sleep(1000);
								
								//On rend la fiche publique
								//MetadataJDBCServices.setPublic(getUuid(), this);
								
								//On indique si la fiche est moissonnee
								//MetadataJDBCServices.setHarvested(getUuid(),  isHarvested(), getConfig());
								return true;
							}
							else
							{
								throw new Exception("The update hasn't been performed");
							}
						}
					}
					else
					{
						throw new Exception ();
					}
			}
			catch (Exception e)
			{	
				throw new Exception(e);
			}
			finally {
				post.releaseConnection();
			}
		
	}

	public String getUuid() {
		return uuid;
	}

	public void setUuid(String uuid) {
		this.uuid = uuid;
	}

	public boolean isHarvested() {
		return harvested;
	}

	public void setHarvested(boolean harvested) {
		this.harvested = harvested;
	}

	
}
